package com.hup.utils.swing.frame;

import com.hup.utils.commons.TextUtil;
import com.hup.utils.commons.exception.AppExceptionHandler;
import com.hup.utils.commons.exception.ErrInfo;
import com.hup.utils.commons.start.DialogHelper;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.commons.start.VersionConfig;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.TitledBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.event.HyperlinkListener;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * 简单的帮助dialog;
 * <pre>
 *      使用 {@link HelpDialogBuilder}进行构建
 *      窗口标题为:帮助(可选+"[ - sub]")
 *      帮助内容来自resource下的html帮助文件
 * </pre>
 */
@Log4j2
public class HelpDialog extends BaseDialog implements HyperlinkListener {

    public static HelpDialogBuilder builder() {
        return new HelpDialogBuilder();
    }

    private JPanel root;
    private JLabel labVersion;
    private JButton btnOk;
    private JEditorPane txtContent;

    private HelpDialog() {
        super("帮助");
        $$$setupUI$$$();
        setContentPane(root);
        getRootPane().setDefaultButton(btnOk);
        btnOk.addActionListener(e -> dispose());
    }

    /**
     * 允许构造/展示后,再次修改界面
     *
     * @param model 如果窗口已经展示了,修改此参数是无效的,swing基础
     */
    private void initView(String subTitle, String helpHtml, boolean showVersion, boolean model,
            boolean escapeCancelable) {
        setModal(model);
        setEscapeCancelable(escapeCancelable);

        if (!TextUtil.isBlank(subTitle)) {
            setSubTitle(subTitle);
        } else {
            setSubTitle(null);
        }

        if (showVersion) {
            VersionConfig versionConfig = SpringContext.getBean(VersionConfig.class);
            labVersion.setText(versionConfig.version);
            labVersion.setToolTipText("发布时间:" + versionConfig.buildTime);
            labVersion.setVisible(true);
        } else {
            labVersion.setVisible(false);
        }

        URL url = this.getClass().getResource(helpHtml);
        log.debug("url={}", url);
        if (url != null) {
            try {
                txtContent.setPage(url);
                txtContent.addHyperlinkListener(this);
            } catch (Exception e) {
                ErrInfo errInfo = AppExceptionHandler.handle("[" + subTitle + "]帮助文件加载异常:<br>", e);
                String content = errInfo.getErrMsg();
                txtContent.setText(content);
            }
        } else {
            String content = "[" + subTitle + "]无帮助文件";
            txtContent.setText(content);
        }
    }

    @Override
    public void hyperlinkUpdate(HyperlinkEvent e) {
        //点击打开连接
        if (e.getEventType() != EventType.ACTIVATED) return;
        URL url = e.getURL();
        log.debug("url={}", url);
        if (url != null) {
            try {
                Desktop.getDesktop().browse(url.toURI());
            } catch (IOException | URISyntaxException err) {
                DialogHelper.show("网址打开失败:", err, this);
            }
        }
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        root = new JPanel();
        root.setLayout(new GridBagLayout());
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new GridBagLayout());
        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        root.add(panel1, gbc);
        panel1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        labVersion = new JLabel();
        labVersion.setText("version");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(0, 0, 3, 0);
        panel1.add(labVersion, gbc);
        final JScrollPane scrollPane1 = new JScrollPane();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        panel1.add(scrollPane1, gbc);
        scrollPane1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        txtContent = new JEditorPane();
        txtContent.setContentType("text/html");
        txtContent.setEditable(false);
        txtContent.setEnabled(true);
        txtContent.setOpaque(false);
        txtContent.putClientProperty("charset", "utf-8");
        scrollPane1.setViewportView(txtContent);
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        root.add(panel2, gbc);
        panel2.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(10, 0, 10, 10), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        final JPanel spacer1 = new JPanel();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel2.add(spacer1, gbc);
        btnOk = new JButton();
        btnOk.setText("确定");
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.weightx = 0.2;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        panel2.add(btnOk, gbc);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return root;
    }

    @NoArgsConstructor(access = AccessLevel.PRIVATE)
    public static class HelpDialogBuilder {
        /**
         * 阻塞:默认是
         */
        boolean model = true;
        /**
         * 在窗口顶部显示版本信息:默认是,使用 {@link SpringContext}, {@link VersionConfig}
         */
        boolean showVersion = true;
        /**
         * ESC关闭窗口
         */
        boolean escapeCancelable = true;

        Dimension minSize = new Dimension(600, 600);

        public HelpDialogBuilder model(boolean model) {
            this.model = model;
            return this;
        }

        public HelpDialogBuilder showVersion(boolean showVersion) {
            this.showVersion = showVersion;
            return this;
        }

        public HelpDialogBuilder escapeCancelable(boolean escapeCancelable) {
            this.escapeCancelable = escapeCancelable;
            return this;
        }

        public HelpDialogBuilder minSize(Dimension minSize) {
            this.minSize = minSize;
            return this;
        }

        public void doShow(BaseWindow window) {
            doShow(window.getBaseTitle(), "/help/" + window.getClass().getSimpleName() + ".html", (Window) window);
        }

        /**
         * 用于代码混淆后,直接传入[helpHtml]
         *
         * @param helpHtml 帮助文件的名字
         */
        public void doShow(BaseWindow window, String helpHtml) {
            doShow(window.getBaseTitle(), "/help/" + helpHtml + ".html", (Window) window);
        }

        /**
         * @param subTitle 子标题,nullable
         * @param helpHtml 帮助文件的路径,如["/help/xxx.html"]
         */
        public void doShow(String subTitle, String helpHtml, Window parent) {
            HelpDialog dialog = SingletonWindowHelper.getWindow(HelpDialog.class);
            if (dialog == null) {
                dialog = new HelpDialog();
                dialog.initView(subTitle, helpHtml, showVersion, model, escapeCancelable);

                if (minSize != null) dialog.setMinimumSize(minSize);
                dialog.pack();
                dialog.setLocationRelativeTo(parent);
            } else {
                dialog.initView(subTitle, helpHtml, showVersion, model, escapeCancelable);
            }

            if (parent != null) dialog.setAlwaysOnTop(parent.isAlwaysOnTop());
            else dialog.setAlwaysOnTop(false);
            dialog.setVisible(true);
        }
    }

}
